package com.uchiha.nova.core.tool.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;
import java.util.Iterator;
import java.util.List;

/**
 * @author 周林静
 * @Date 2022-03-26,0026 15:12
 * @Version 1.0
 */
public class OperateImageUtils {
    private Logger log = LoggerFactory.getLogger(getClass());
    public static final String DEFAULT_IMG_NAME = "tmpImgName";
    public static final String DEFAULT_IMG_FORMAT = "jpg";
    public static final String DEFAULT_DATA_URI = "data:application/octet-stream;base64,";
    private int x;
    private int y;
    private int width;
    private int height;

    public OperateImageUtils() {
    }

    /**
     * 构造方法
     * @param x
     * @param y
     * @param width
     * @param height
     */
    public OperateImageUtils(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    /***
     * 构造方法  传入一个集合坐标值  算出 x，y,width,height
     * @param bboxes
     */
    public OperateImageUtils(List<List<Integer>> bboxes) {
        int upLeftX = ((Integer) ((List) bboxes.get(0)).get(0)).intValue();
        int upLeftY = ((Integer) ((List) bboxes.get(0)).get(1)).intValue();
        int upRightX = ((Integer) ((List) bboxes.get(1)).get(0)).intValue();
        int downLeftY = ((Integer) ((List) bboxes.get(3)).get(1)).intValue();
        int width = Math.abs(upRightX - upLeftX);
        int height = Math.abs(downLeftY - upLeftY);
        this.x = upLeftX;
        this.y = upLeftY;
        this.width = width;
        this.height = height;
    }

    /**
     *
     * @param imgBytes
     * @param suffix
     * @return
     */
    public byte[] cut(byte[] imgBytes, String suffix) {
        try {
            ImageInputStream iis = null;
            FileInputStream is = byteToFile(imgBytes, "tmpImgName");
            Iterator it = ImageIO.getImageReadersByFormatName(suffix);
            ImageReader reader = (ImageReader) it.next();
            iis = ImageIO.createImageInputStream(is);
            reader.setInput(iis, true);
            ImageReadParam param = reader.getDefaultReadParam();
            Rectangle rect = new Rectangle(this.x, this.y, this.width, this.height);
            param.setSourceRegion(rect);
            BufferedImage bi = reader.read(0, param);
            byte[] cutImg = imageToBytes(bi, "jpg");
            return cutImg;
        } catch (IOException e) {
            this.log.error("image file cut fail, error information is : {} ", e);
        }
        return null;
    }

    public byte[] imageToBytes(BufferedImage bImage, String format) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(bImage, format, out);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toByteArray();
    }

    public int getX() {
        return this.x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return this.y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getWidth() {
        return this.width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return this.height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    /**
     * 	通过文件地址 获取到文件 将文件转化成 byte 数组
     * @param fileUrl
     * @return
     */
    public byte[] getUrlFileData(String fileUrl) {
        System.out.println("getUrlFileData:"+fileUrl);
        try {
            URL url = new URL(fileUrl);
            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
            httpConn.connect();
            InputStream cin = httpConn.getInputStream();
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = cin.read(buffer)) != -1) {
                outStream.write(buffer, 0, len);
            }
            cin.close();
            byte[] fileData = outStream.toByteArray();
            outStream.close();
            return fileData;
        } catch (IOException e) {
            this.log.error("get imageFile by fileUrl fail, error information is : {} ", e);
        }
        return null;
    }

    /**
     * 将byte 数组 转化成文件输入流
     * @param bytes
     * @param fileName
     * @return
     */
    public FileInputStream byteToFile(byte[] bytes, String fileName) {
        File file = new File(fileName);
        FileInputStream fileInputStream = null;
        try {
            OutputStream output = new FileOutputStream(file);
            BufferedOutputStream bufferedOutput = new BufferedOutputStream(output);
            bufferedOutput.write(bytes);
            fileInputStream = new FileInputStream(file);
            file.deleteOnExit();
            return fileInputStream;
        } catch (IOException e) {
            this.log.error("bytes to Image file fail, error information is : {} ", e);
        }
        return fileInputStream;
    }

    /**
     *
     * @param imageUrl
     * @param suffix
     * @return
     */
    public String getBase64Url(String imageUrl, String suffix) {

        byte[]  imgBuffer = getUrlFileData(imageUrl);

        String result = Base64.getEncoder().encodeToString(imgBuffer);
        return result;
    }

    public byte[] getBytesByBase64(String base64Uri) {
        String base64Code = base64Uri.substring(base64Uri.indexOf(",") + 1);
        byte[] buffer = Base64.getDecoder().decode(base64Code);
        return buffer;
    }

    /**
     * 	将本地文件转换成字节数组
     * @param
     * @return
     */
    public byte[] getFileData(String filePath) {
        try {
            File file = new File(filePath);
            InputStream cin =new FileInputStream(file);
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = cin.read(buffer)) != -1) {
                outStream.write(buffer, 0, len);
            }
            cin.close();
            byte[] fileData = outStream.toByteArray();
            outStream.close();
            return fileData;
        } catch (IOException e) {
            this.log.error("get imageFile by fileUrl fail, error information is : {} ", e);
        }
        return null;
    }


    /**
     *
     * @param imageUrl
     * @param suffix
     * @return
     */
    public String getBase64Url_Flie(String imageUrl, String suffix) {
        byte[] imgBuffer = null;
        imgBuffer = getFileData(imageUrl);
        if ((suffix.isEmpty()) || (null == suffix)) {
            suffix = "jpg";
        }
        byte[] cutImg = cut(imgBuffer, suffix);
        String result = Base64.getEncoder().encodeToString(cutImg);
        return "data:application/octet-stream;base64," + result;
    }
}
